import time,os
from rich.progress import Progress
from support.utils.toolkit import ToolKit as tk
from support.suit.qe import Analysis, DI
from support.file.xls import Excel
from support.ui.console import Log

class Report:
    RET_LOAD_SUCCESS = 0
    RET_LOAD_FAILED_ALL = 1
    RET_LOAD_FAILED_EFFORT = 2
    RET_LOAD_FAILED_DEFECT = 3
    DefectHeader = ["问题单号", "问题单当前业务状态", "问题单创建时间", "严重程度", "特性", "子系统", "模块", "问题责任来源", "缺陷年龄", "发现问题活动", "触发因素", "结果影响", "问题发现阶段", "问题根源对象大类", "问题根源对象小类"]
    EffortHeader = ["模块/特性", "B版本移植代码量(KLOC)", "B版本新增代码量(KLOC)", "B版本修改代码量(KLOC)", "移植代码折算系数(0~0.5)", "本轮测试执行工作量(人时)", "历史测试执行工作量(人时)", "有效代码量(KLOC)", "累计测试执行工作量(人时)", "累计测试执行工作密度(人时/KLOC)"]
    ReportDataHeader = {
        "defectsData":{"label":"当前R版本缺陷数据", "data":["模块/特性", "累计缺陷总数加权", "致命缺陷", "严重缺陷", "一般缺陷", "提示缺陷", "累计缺陷密度(缺陷数/KLOC)"]},
        "effect":{"label":"工作量及代码规模数据", "data":EffortHeader},
        "fourquadrants":{"label":"四象限分析(请至少保留两个模块/特性数据行)", "data":["模块/特性", "累计人时/KLOC", "缺陷数/KLOC", "质量评估"]}
        }
    def __init__(self, defectpath, effortpath, reportpath):
        self.path = {"defect":defectpath, "effort":effortpath, "report":reportpath}

    def exportEffortFile(self):
        header = ["模块/特性", "B版本移植代码量(KLOC)", "B版本新增代码量(KLOC)", "B版本修改代码量(KLOC)", "移植代码折算系数(0~0.5)", "本轮测试执行工作量(人时)", "历史测试执行工作量(人时)"]
        excel = Excel(self.path["effort"], 'effort.xlsx')
        excel.writeRowData("effort", 1, 1, header)
        excel.save(close=True)

    def __loadDataFromExcel(self, frompath, header, sheetname, func):
        dataArr = []
        columns = []
        cleanData = {}
        for path, pathnames, filenames in os.walk(frompath):
            for filename in filenames:
                if(os.path.splitext(filename)[-1] in ['.xlsx', '.xls']):
                    excel = Excel(path, filename)
                    columns.clear()
                    excel.getColumns(sheetname, 0, header, columns)
                    size = excel.getMaxSize(sheetname)
                    with Progress() as progress:
                        task_load = progress.add_task("[cyan]Load Data From...{}".format(filename), total=size['row'])
                        for row in range(1, size['row']):
                            dataArr.clear()
                            excel.readDataSpecColumns(sheetname, row, columns, dataArr)
                            progress.update(task_load, advance=0.5)
                            func(dataArr, cleanData)
                            progress.update(task_load, advance=0.5)
                        progress.update(task_load, completed=size["row"])
                    excel.close()
        return cleanData

    def writeDefectData(self, resultExecl, sheetname, defectData, effortData, currentRow):
        sum = [0,0,0,0,0,0]
        for feature in defectData:
            di = DI()
            di.append(critical=defectData[feature]["critical"], major=defectData[feature]["major"],
            minor=defectData[feature]["minor"], warning=defectData[feature]["warning"])
            resultExecl.writeRowData(sheetname, currentRow, 1, feature)
            resultExecl.writeRowData(sheetname, currentRow, 2, di.value)
            resultExecl.writeRowData(sheetname, currentRow, 3, di.critical)
            resultExecl.writeRowData(sheetname, currentRow, 4, di.major)
            resultExecl.writeRowData(sheetname, currentRow, 5, di.minor)
            resultExecl.writeRowData(sheetname, currentRow, 6, di.warning)
            density = ""
            if(feature in effortData):
                density = round(1 + (di.value / effortData[feature]["ecs"]), 2) -1
            defectData[feature]["density"] = density
            resultExecl.writeRowData(sheetname, currentRow, 7, density)
            currentRow += 1
            sum[0] += di.value
            sum[1] += di.critical
            sum[2] += di.major
            sum[3] += di.minor
            sum[4] += di.warning
            if(density != ""):
                sum[5] += density
        resultExecl.writeRowData(sheetname, currentRow, 1, ["合计"] + sum, {'color':'FFFFFF','fill':'5B9BD5','b':True})
        return currentRow + 1

    def loadDefectsData(self, dataArr, cleanData):
        if(tk.isNone(dataArr[4]["value"]) and tk.isNone(dataArr[5]["value"])):
            return
        feature = dataArr[4]["value"] if not tk.isNone(dataArr[4]["value"]) else dataArr[5]["value"]
        level = dataArr[3]["value"]
        if(feature not in cleanData):
            cleanData[feature] = {}
            cleanData[feature]["critical"] = 0
            cleanData[feature]["major"] = 0
            cleanData[feature]["minor"] = 0
            cleanData[feature]["warning"] = 0
        if(level == '致命'):
            cleanData[feature]["critical"] += 1
        elif(level == '严重'):
            cleanData[feature]["major"] += 1
        elif(level == '一般'):
            cleanData[feature]["minor"] += 1
        elif(level == '提示'):
            cleanData[feature]["warning"] += 1

    def loadEffortData(self, dataArr, cleanData):
        if(dataArr[0]["value"] is None):
            return
        feature = dataArr[0]["value"]
        cleanData[feature] = {}
        cleanData[feature]["ported"] = dataArr[1]["value"]
        cleanData[feature]["new"] = dataArr[2]["value"]
        cleanData[feature]["modified"] = dataArr[3]["value"]
        cleanData[feature]["factor"] = dataArr[4]["value"]
        cleanData[feature]["te"] = dataArr[5]["value"]
        cleanData[feature]["hte"] = dataArr[6]["value"]
        
    def writeEffortData(self, resultExecl, sheetname, cleanData, currentRow):
        sum = [0,0,0,0,0,0,0,0,0]
        for feature in cleanData:
            resultExecl.writeRowData(sheetname, currentRow, 1, feature)
            resultExecl.writeRowData(sheetname, currentRow, 2, cleanData[feature]["ported"])
            resultExecl.writeRowData(sheetname, currentRow, 3, cleanData[feature]["new"])
            resultExecl.writeRowData(sheetname, currentRow, 4, cleanData[feature]["modified"])
            resultExecl.writeRowData(sheetname, currentRow, 5, cleanData[feature]["factor"])
            resultExecl.writeRowData(sheetname, currentRow, 6, cleanData[feature]["te"])
            resultExecl.writeRowData(sheetname, currentRow, 7, cleanData[feature]["hte"])
            col = 8
            ecs = cleanData[feature]["ported"] * cleanData[feature]["factor"] + cleanData[feature]["new"] + cleanData[feature]["modified"]
            ecs = round(1 + ecs, 2) - 1
            cleanData[feature]["ecs"] = ecs
            resultExecl.writeRowData(sheetname, currentRow, col, ecs)
            col += 1
            ate = cleanData[feature]["te"] + cleanData[feature]["hte"]
            ate = round(1 + ate, 1) - 1
            resultExecl.writeRowData(sheetname, currentRow, col, ate)
            col += 1
            density = round(1 + ate/ecs, 2) -1
            cleanData[feature]["density"] = density
            resultExecl.writeRowData(sheetname, currentRow, col, density)
            currentRow += 1
            sum[0] += cleanData[feature]["ported"]
            sum[1] += cleanData[feature]["new"]
            sum[2] += cleanData[feature]["modified"]
            sum[3] += cleanData[feature]["factor"]
            sum[4] += cleanData[feature]["te"]
            sum[5] += cleanData[feature]["hte"]
            sum[6] += ecs
            sum[7] += ate
            sum[8] += density
        resultExecl.writeRowData("测试数据", currentRow, 1, ["合计"] + sum, {'color':'FFFFFF','fill':'5B9BD5','b':True})
        return currentRow + 1

    def loadData(self):
        effortData = self.__loadDataFromExcel(self.path["effort"], Report.EffortHeader, "effort", self.loadEffortData)
        defectData = self.__loadDataFromExcel(self.path["defect"], Report.DefectHeader, "问题单导出", self.loadDefectsData)
        self.data = {"effort":effortData, "defect":defectData}
        if(tk.isNone(effortData) and tk.isNone(defectData)):
            return Report.RET_LOAD_FAILED_ALL
        elif(tk.isNone(effortData)):
            return Report.RET_LOAD_FAILED_EFFORT
        elif(tk.isNone(defectData)):
            return Report.RET_LOAD_FAILED_DEFECT
        return Report.RET_LOAD_SUCCESS
        
    def writeFourQuadrants(self, qtp, qtd, excel, sheetname, defectData, effortData, currentRow):
        for feature in effortData:
            tpk = effortData[feature]["density"]
            dpk = ""
            if(feature in defectData):
                dpk = defectData[feature]["density"]
            qa = "" if dpk == "" else Analysis.fourquadrant(tpk, dpk, qtp, qtd)
            excel.writeRowData(sheetname, currentRow, 1, feature)
            excel.writeRowData(sheetname, currentRow, 2, tpk)
            excel.writeRowData(sheetname, currentRow, 3, dpk)
            if(qa != ""):
                if(qa["status"] == Analysis.FQ_STATE_UNSTEADY):
                    excel.writeRowData(sheetname, currentRow, 4, "不稳定")
                elif(qa["status"] == Analysis.FQ_STATE_STABLE):
                    excel.writeRowData(sheetname, currentRow, 4, "稳定")
                elif(qa["status"] == Analysis.FQ_STATE_EXTREMELY_UNSTABLE):
                    excel.writeRowData(sheetname, currentRow, 4, "极不稳定")
                elif(qa["status"] == Analysis.FQ_STATE_NOT_SURE):
                    excel.writeRowData(sheetname, currentRow, 4, "不确定")
            else:
                excel.writeRowData(sheetname, currentRow, 4, "")
            currentRow += 1
        excel.writeRowData(sheetname, currentRow, 1, ["质量目标", qtp, qtd, ""], {'color':'FFFFFF','fill':'5B9BD5','b':True})
        return currentRow
        



    def export(self, qulity_p, qulity_d):
        resultExecl = Excel(self.path["report"], time.strftime("report-%Y%m%d_%H_%M_%S.xlsx"))
        currentRow = 1
        resultExecl.writeRowData("测试数据", currentRow, 1, Report.ReportDataHeader["effect"]["label"], {'color':'FFFFFF','fill':'00B0F0','b':True})
        resultExecl.merge("测试数据", currentRow, 1, currentRow, 1 + len(Report.ReportDataHeader["effect"]["data"]) - 1)
        resultExecl.writeRowData("测试数据", currentRow + 1, 1, Report.ReportDataHeader["effect"]["data"], {'color':'FFFFFF','fill':'5B9BD5','b':True})
        currentRow += self.writeEffortData(resultExecl, "测试数据", self.data["effort"], currentRow + 2)
        resultExecl.writeRowData("测试数据", currentRow, 1, Report.ReportDataHeader["defectsData"]["label"], {'color':'FFFFFF','fill':'00B0F0','b':True})
        resultExecl.merge("测试数据", currentRow, 1, currentRow, 1 + len(Report.ReportDataHeader["defectsData"]["data"]) - 1)
        resultExecl.writeRowData("测试数据", currentRow + 1, 1, Report.ReportDataHeader["defectsData"]["data"], {'color':'FFFFFF','fill':'5B9BD5','b':True})
        self.writeDefectData(resultExecl, "测试数据", self.data["defect"], self.data["effort"], currentRow + 2)
        currentRow = 1
        resultExecl.writeRowData("四象限分析", currentRow, 1, Report.ReportDataHeader["fourquadrants"]["label"], {'color':'FFFFFF','fill':'00B0F0','b':True})
        resultExecl.merge("四象限分析", currentRow, 1, currentRow, 1 + len(Report.ReportDataHeader["fourquadrants"]["data"]) - 1)
        resultExecl.writeRowData("四象限分析", currentRow + 1, 1, Report.ReportDataHeader["fourquadrants"]["data"], {'color':'FFFFFF','fill':'5B9BD5','b':True})
        self.writeFourQuadrants(qulity_p, qulity_d, resultExecl, "四象限分析", self.data["defect"], self.data["effort"], currentRow + 2)
        resultExecl.save(close=True)